package org.paradigmshift.cumulusfracto.filesystem;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.element.GenericConfigElement;
import org.alfresco.jlan.debug.Debug;
import org.alfresco.jlan.debug.DebugConfigSection;
import org.alfresco.jlan.netbios.win32.Win32NetBIOS;
import org.alfresco.jlan.server.auth.CifsAuthenticator;
import org.alfresco.jlan.server.auth.acl.AccessControlList;
import org.alfresco.jlan.server.config.ConfigurationListener;
import org.alfresco.jlan.server.config.CoreServerConfigSection;
import org.alfresco.jlan.server.config.GlobalConfigSection;
import org.alfresco.jlan.server.config.InvalidConfigurationException;
import org.alfresco.jlan.server.config.SecurityConfigSection;
import org.alfresco.jlan.server.config.ServerConfiguration;
import org.alfresco.jlan.server.core.DeviceContextException;
import org.alfresco.jlan.server.filesys.DiskDeviceContext;
import org.alfresco.jlan.server.filesys.DiskInterface;
import org.alfresco.jlan.server.filesys.DiskSharedDevice;
import org.alfresco.jlan.server.filesys.FilesystemsConfigSection;
import org.alfresco.jlan.server.filesys.SrvDiskInfo;
import org.alfresco.jlan.server.filesys.VolumeInfo;
import org.alfresco.jlan.smb.Dialect;
import org.alfresco.jlan.smb.DialectSelector;
import org.alfresco.jlan.smb.server.CIFSConfigSection;
import org.alfresco.jlan.smb.server.SMBSrvSession;
import org.alfresco.jlan.util.IPAddress;
import org.alfresco.jlan.util.Platform;
import org.alfresco.jlan.util.StringList;
import org.alfresco.jlan.util.X64;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import com.google.gdata.client.docs.DocsService;

/**
 * Aerial XML File Server Configuration Class
 * 
 * <p>
 * XML implementation of the SMB server configuration.
 * 
 * @author gkspencer
 * @author the.tiki.god
 */
public class CumulusFractoXmlServerConfig  {
	
//	// Constants
//	// Node type for an Element
//	private static final int ELEMENT_TYPE = 1;
//	
//	// CIFS session debug type strings. Must match the bit mask order.
//	private static final String DEBUG_FLAG_REGEX = "(\\w+)";
//	private static enum SESSION_DEBUG_ENUM { NETBIOS, STATE, RXDATA, TXDATA, DUMPDATA, NEGOTIATE, TREE, SEARCH, INFO, FILE, FILEIO, TRANSACT, ECHO, ERROR, IPC, LOCK, PKTTYPE, DCERPC, STATECACHE, TIMING, NOTIFY, STREAMS, SOCKET, PKTPOOL, PKTSTATS, THREADPOOL, BENCHMARK; };
//	private static final int DEFAULT_SESSDEBUG = SMBSrvSession.DBG_ERROR + SMBSrvSession.DBG_INFO + SMBSrvSession.DBG_SEARCH + SMBSrvSession.DBG_TREE + SMBSrvSession.DBG_TRAN + SMBSrvSession.DBG_STATE;
//	
//	// Dialects
//	private static final String SMB_DIALECT_REGEX = "(\\w+)";
//	private static enum SMB_DIALECTS { CORE, LANMAN, NT; };
//	
//	// Platforms
//	private static final String PLATFORMS_REGEX = "(\\w+)";
//	
//	// Aliases
//	private static final String ALIASES_REGEX = "(\\w+)";
//	
//	// Default thread pool size
//	private static final int DefaultThreadPoolInit = 25;
//	private static final int DefaultThreadPoolMax = 50;
//	
//	// Default memory pool settings
//	private static final int[] DefaultMemoryPoolBufSizes = { 256, 4096, 16384, 65536 };
//	private static final int[] DefaultMemoryPoolInitAlloc = { 20, 20, 5, 5 };
//	private static final int[] DefaultMemoryPoolMaxAlloc = { 100, 50, 50, 50 };
//	
//	// Maximum session timeout
//	private static final int MaxSessionTimeout = 60 * 60; // 1 hour
//	
//	/**
//	 * Default constructor
//	 * 
//	 * TODO: Add parameters for the Google docs service and a shared drive
//	 */
//	public CumulusFractoXmlServerConfig() {
//
//		super( "" );
//	}
//	
//	/**
//	 * Load the configuration from the specified file.
//	 * 
//	 * @param fileName
//	 *            java.lang.String
//	 * @exception IOException
//	 * @exception InvalidConfigurationException
//	 */
//	public final void loadConfiguration( String fileName ) throws IOException, InvalidConfigurationException {
//
//		// Open the configuration file
//		Reader reader = new InputStreamReader( new FileInputStream( fileName ) );
//		
//		// Reset the current configuration to the default settings
//		removeAllConfigSections();
//		
//		// Load and parse the XML configuration document
//		try {
//			
//			// Load the configuration from the XML file
//			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//			DocumentBuilder builder = factory.newDocumentBuilder();
//			InputSource xmlSource = new InputSource( reader );
//			Document doc = builder.parse( xmlSource );
//			
//			// Access the root of the XML document, get a list of the child nodes
//			Element root = doc.getDocumentElement();
//			NodeList childNodes = root.getChildNodes();
//			
//			// Create the core server configuration
//			CoreServerConfigSection coreConfig = new CoreServerConfigSection( this );
//			coreConfig.setMemoryPool( DefaultMemoryPoolBufSizes, DefaultMemoryPoolInitAlloc, DefaultMemoryPoolMaxAlloc );
//			coreConfig.setThreadPool( DefaultThreadPoolInit, DefaultThreadPoolMax );
//			
//			// Create the global configuration section
//			new GlobalConfigSection( this );
//			new FilesystemsConfigSection( this );
//			
//			// Use the default access control manager
//			SecurityConfigSection secConfig = new SecurityConfigSection( this );
//			secConfig.setAccessControlManager( "org.alfresco.jlan.server.auth.acl.DefaultAccessControlManager", new GenericConfigElement( "aclManager" ) );
//			
//			// Process the shares element
//			procSMBServerElement( getChildNode( "SMB", childNodes ) );
//			procDebugElement( getChildNode( "debug", childNodes ) );
//			
//			// TODO: remove this to add shares dynamically
//			//addDiskShare( new FilesystemsConfigSection( this ), "Test", "Test" );
//		}
//		catch ( Exception ex ) {
//			
//			// Rethrow the exception as a configuration exeception
//			throw new InvalidConfigurationException( "XML error", ex );
//		}
//		finally {
//			
//			// Close the input file
//			reader.close();
//		}
//	}
//	
//	/**
//	 * Process the SMB server XML element
//	 * 
//	 * @param smb Element
//	 * @exception InvalidConfigurationException
//	 */
//	protected final void procSMBServerElement( Element smb ) throws InvalidConfigurationException {
//
//		// Check if the SMB element is valid
//		if ( smb == null ) {
//			
//			throw new InvalidConfigurationException( "SMB section must be specified" );
//		}
//		
//		// Create the CIFS server configuration
//		CIFSConfigSection cifsConfig = new CIFSConfigSection( this );
//		procHostElement( getChildNode( "host", smb.getChildNodes() ), cifsConfig );
//		
//		// Debug settings are now specified within the SMB server configuration
//		// block
//		Element elem = getChildNode( "netbiosDebug", smb.getChildNodes() );
//		if ( elem != null ) {
//			
//			cifsConfig.setNetBIOSDebug( true );
//		}
//		
//		elem = getChildNode( "announceDebug", smb.getChildNodes() );
//		if ( elem != null ) {
//			
//			cifsConfig.setHostAnnounceDebug( true );
//		}
//		
//		elem = getChildNode( "sessionDebug", smb.getChildNodes() );
//		if ( elem != null ) {
//			
//			// Check for session debug flags
//			String flags = elem.getAttribute( "flags" );
//			int sessDbg = DEFAULT_SESSDEBUG;
//			
//			if ( flags != null ) {
//				
//				Pattern pattern = Pattern.compile( DEBUG_FLAG_REGEX );
//				Matcher matcher = pattern.matcher( flags );
//				
//				// Clear the default debug and parse the flags
//				sessDbg = 0;
//				while ( matcher.find() ) {
//					
//					// Find the debug flag name
//					String group = matcher.group();
//					try {
//						
//						SESSION_DEBUG_ENUM debug = SESSION_DEBUG_ENUM.valueOf( group.toUpperCase() );
//						sessDbg += 1 << debug.ordinal();
//					}
//					catch ( Exception e ) {
//						
//						throw new InvalidConfigurationException( "Invalid session debug flag, " + group );
//					}
//				}
//			}
//			
//			cifsConfig.setSessionDebugFlags( sessDbg );
//		}
//		
//		// Check if NIO based code should be disabled
//		if ( getChildNode( "disableNIO", smb.getChildNodes() ) != null ) {
//			
//			cifsConfig.setDisableNIOCode( true );
//		}
//		
//		// Check if an authenticator has been specified
//		Element authElem = getChildNode( "authenticator", smb.getChildNodes() );
//		if ( authElem != null ) {
//			
//			// Get the authenticator class and security mode
//			Element classElem = getChildNode( "class", authElem.getChildNodes() );
//			String authClass = null;
//			if ( classElem == null ) {
//				
//				// Check if the authenticator type has been specified
//				String authType = authElem.getAttribute( "type" );
//				if ( authType == null ) {
//					
//					throw new InvalidConfigurationException( "Authenticator class not specified" );
//				}
//				
//				// Check the authenticator type and set the appropriate authenticator class
//				if ( authType.equalsIgnoreCase( "local" ) ) {
//					
//					authClass = "org.alfresco.jlan.server.auth.LocalAuthenticator";
//				}
//				else if ( authType.equalsIgnoreCase( "passthru" ) ) {
//					
//					authClass = "org.alfresco.jlan.server.auth.passthru.PassthruAuthenticator";
//				}
//				else if ( authType.equalsIgnoreCase( "enterprise" ) ) {
//					
//					authClass = "org.alfresco.jlan.server.auth.EnterpriseCifsAuthenticator";
//				}
//			}
//			else {
//				
//				// Set the authenticator class
//				authClass = getText( classElem );
//			}
//			
//			Element modeElem = getChildNode( "mode", authElem.getChildNodes() );
//			int accessMode = CifsAuthenticator.USER_MODE;
//			
//			if ( modeElem != null ) {
//				
//				// Validate the authenticator mode
//				String mode = getText( modeElem );
//				if ( mode.equalsIgnoreCase( "share" ) ) {
//					
//					accessMode = CifsAuthenticator.SHARE_MODE;
//				}
//				else if ( !mode.equalsIgnoreCase( "user" ) ) {
//					
//					throw new InvalidConfigurationException( "Invalid authentication mode, must be USER or SHARE" );
//				}
//			}
//			
//			// Get the allow guest setting
//			Element allowGuest = getChildNode( "allowGuest", authElem.getChildNodes() );
//			
//			// Get the parameters for the authenticator class
//			ConfigElement params = buildConfigElement( authElem, null );
//			cifsConfig.setAuthenticator( authClass, params, accessMode, allowGuest != null ? true : false );
//		}
//	}
//	
//	/**
//	 * Process the host XML element
//	 * 
//	 * @param host Element
//	 * @param cifsConfig CIFSConfigSection
//	 * @exception InvalidConfigurationException
//	 */
//	protected final void procHostElement( Element host, CIFSConfigSection cifsConfig ) throws InvalidConfigurationException {
//
//		// Check if the host element is valid
//		if ( host == null ) {
//			
//			throw new InvalidConfigurationException( "Host section must be specified" );
//		}
//		
//		// Get the host name attribute
//		String hostName = host.getAttribute( "name" );
//		if ( hostName == null || hostName.length() == 0 ) {
//			
//			throw new InvalidConfigurationException( "Host name not specified or invalid" );
//		}
//		cifsConfig.setServerName( hostName.toUpperCase() );
//		
//		// If the global server name has not been set then use the CIFS server name
//		if ( getServerName() == null ) {
//			
//			setServerName( cifsConfig.getServerName() );
//		}
//		
//		// Get the domain name
//		String domain = host.getAttribute( "domain" );
//		if ( domain != null && domain.length() > 0 ) {
//			
//			cifsConfig.setDomainName( domain.toUpperCase() );
//		}
//		
//		// Get the enabled SMB dialects
//		Element smbDialectsElem = getChildNode( "smbdialects", host.getChildNodes() );
//		if ( smbDialectsElem != null ) {
//			
//			// Clear all configured SMB dialects
//			DialectSelector dialectSelector = cifsConfig.getEnabledDialects();
//			dialectSelector.ClearAll();
//			
//			// Parse the SMB dilaects list
//			String dialects = getText( smbDialectsElem );
//			if ( dialects != null ) {
//				
//				Pattern pattern = Pattern.compile( SMB_DIALECT_REGEX );
//				Matcher matcher = pattern.matcher( dialects );
//				
//				while ( matcher.find() ) {
//					
//					String group = matcher.group();
//					try {
//						
//						SMB_DIALECTS dialect = SMB_DIALECTS.valueOf( matcher.group().toUpperCase() );
//						switch ( dialect ) {
//							
//							case CORE:
//								// Enable core dialects
//								dialectSelector.AddDialect( Dialect.Core );
//								dialectSelector.AddDialect( Dialect.CorePlus );
//								break;
//								
//							case LANMAN:
//								// Enable the LanMAn dialects
//								dialectSelector.AddDialect( Dialect.DOSLanMan1 );
//								dialectSelector.AddDialect( Dialect.DOSLanMan2 );
//								dialectSelector.AddDialect( Dialect.LanMan1 );
//								dialectSelector.AddDialect( Dialect.LanMan2 );
//								dialectSelector.AddDialect( Dialect.LanMan2_1 );
//								break;
//								
//							case NT:
//								// Enable the NT dialect
//								dialectSelector.AddDialect( Dialect.NT );
//								break;
//								
//							default:
//								throw new InvalidConfigurationException( "Invalid SMB dialect, " + group );
//						}
//					}
//					catch ( Exception e ) {
//						
//						throw new InvalidConfigurationException( "Invalid SMB dialect, " + group );
//					}
//				}
//			}
//			
//			// Set the enabled server SMB dialects
//			cifsConfig.setEnabledDialects( dialectSelector );
//		}
//		
//		// Check for a server comment
//		Element commentElement = getChildNode( "comment", host.getChildNodes() );
//		if ( commentElement != null ) {
//			
//			cifsConfig.setComment( getText( commentElement ) );
//		}
//		
//		// Check for a bind address
//		Element bindToElement = getChildNode( "bindto", host.getChildNodes() );
//		if ( bindToElement != null ) {
//			
//			// Check if the network adapter name has been specified
//			if ( bindToElement.hasAttribute( "adapter" ) ) {
//				
//				// Get the IP address for the adapter and set it for the server
//				InetAddress bindAddr = parseAdapterName( bindToElement.getAttribute( "adapter" ) );
//				cifsConfig.setSMBBindAddress( bindAddr );
//			}
//			else {
//				
//				// Validate the bind address
//				String bindText = getText( bindToElement );
//				try {
//					
//					// Check the bind address and set it for the server
//					InetAddress bindAddr = InetAddress.getByName( bindText );
//					cifsConfig.setSMBBindAddress( bindAddr );
//				}
//				catch ( UnknownHostException ex ) {
//					
//					throw new InvalidConfigurationException( ex.toString() );
//				}
//			}
//		}
//		
//		// Check if the host announcer should be enabled
//		Element hostAnnounceElement = getChildNode( "hostAnnounce", host.getChildNodes() );
//		if ( hostAnnounceElement != null ) {
//			
//			// Check for an announcement interval
//			String interval = hostAnnounceElement.getAttribute( "interval" );
//			if ( interval != null && interval.length() > 0 ) {
//				
//				try {
//					
//					cifsConfig.setHostAnnounceInterval( Integer.parseInt( interval ) );
//				}
//				catch ( NumberFormatException ex ) {
//					
//					throw new InvalidConfigurationException( "Invalid host announcement interval" );
//				}
//			}
//			
//			// Check if the domain name has been set, this is required if the host announcer is enabled
//			if ( cifsConfig.getDomainName() == null ) {
//				
//				throw new InvalidConfigurationException( "Domain name must be specified if host announcement is enabled" );
//			}
//			
//			// Enable host announcement
//			cifsConfig.setHostAnnouncer( true );
//		}
//		
//		// Check for a host announcer port
//		Element hostAnnouncerPortElement = getChildNode( "HostAnnouncerPort", host.getChildNodes() );
//		if ( hostAnnouncerPortElement != null ) {
//			
//			try {
//				
//				cifsConfig.setHostAnnouncerPort( Integer.parseInt( getText( hostAnnouncerPortElement ) ) );
//				int hostAnnouncerPort = cifsConfig.getHostAnnouncerPort();
//				if ( hostAnnouncerPort <= 0 || hostAnnouncerPort >= 65535 ) {
//					
//					throw new InvalidConfigurationException( "Host announcer port out of valid range" );
//				}
//			}
//			catch ( NumberFormatException ex ) {
//				
//				throw new InvalidConfigurationException( "Invalid host announcer port" );
//			}
//		}
//		
//		// Check if NetBIOS SMB is enabled
//		Element netBiosSmbElement = getChildNode( "netBIOSSMB", host.getChildNodes() );
//		if ( netBiosSmbElement != null ) {
//			
//			// Check if NetBIOS over TCP/IP is enabled for the current platform
//			if ( netBiosSmbElement.hasAttribute( "platforms" ) ) {
//				
//				// Check if the current platform is included
//				if ( isCurrentPlatformIncluded( netBiosSmbElement.getAttribute( "platforms" ) ) ) {
//					
//					// Enable the NetBIOS SMB support
//					cifsConfig.setNetBIOSSMB( true );
//					
//					// Check for the session port
//					String sessionPortAttribute = netBiosSmbElement.getAttribute( "sessionPort" );
//					if ( sessionPortAttribute != null && sessionPortAttribute.length() > 0 ) {
//						
//						Integer sessionPort = convertStringToPortNumber( sessionPortAttribute );
//						if ( sessionPort == null ) {
//							
//							throw new InvalidConfigurationException( "Invalid NetBIOS SMB session port" );
//						}
//						cifsConfig.setSessionPort( sessionPort );
//					}
//					
//					// Check for the datagram port
//					String datagramPortAttribute = netBiosSmbElement.getAttribute( "datagramPort" );
//					if ( datagramPortAttribute != null && datagramPortAttribute.length() > 0 ) {
//						
//						Integer datagramPort = convertStringToPortNumber( datagramPortAttribute );
//						if ( datagramPort == null ) {
//							
//							throw new InvalidConfigurationException( "Invalid NetBIOS SMB datagram port" );
//						}
//						cifsConfig.setDatagramPort( datagramPort );
//					}
//					
//					// Check for the name server port
//					String namingPortAttribute = netBiosSmbElement.getAttribute( "namingPort" );
//					if ( namingPortAttribute != null && namingPortAttribute.length() > 0 ) {
//						
//						Integer namingPort = convertStringToPortNumber( namingPortAttribute );
//						if ( namingPort == null ) {
//							
//							throw new InvalidConfigurationException( "Invalid NetBIOS SMB naming port" );
//						}
//						cifsConfig.setNameServerPort( namingPort );
//					}
//					
//					// Check for a bind address
//					String bindToAddress = netBiosSmbElement.getAttribute( "bindto" );
//					if ( bindToAddress != null && bindToAddress.length() > 0 ) {
//						
//						// Validate the bind address
//						try {
//							
//							// Check and set the bind address for the NetBIOS name server
//							InetAddress bindAddr = InetAddress.getByName( bindToAddress );
//							cifsConfig.setNetBIOSBindAddress( bindAddr );
//						}
//						catch ( UnknownHostException ex ) {
//							
//							throw new InvalidConfigurationException( ex.toString() );
//						}
//					}
//					else if ( netBiosSmbElement.hasAttribute( "adapter" ) ) {
//						
//						// Get the bind address via the network adapter name
//						InetAddress bindAddr = parseAdapterName( netBiosSmbElement.getAttribute( "adapter" ) );
//						cifsConfig.setNetBIOSBindAddress( bindAddr );
//					}
//					else if ( cifsConfig.hasSMBBindAddress() ) {
//						
//						// Use the SMB bind address for the NetBIOS name server
//						cifsConfig.setNetBIOSBindAddress( cifsConfig.getSMBBindAddress() );
//					}
//				}
//				else {
//					
//					// Disable the NetBIOS SMB support
//					cifsConfig.setNetBIOSSMB( false );
//				}
//			}
//		}
//		else {
//			
//			// Disable NetBIOS SMB support
//			cifsConfig.setNetBIOSSMB( false );
//		}
//		
//		// Check if TCP/IP SMB is enabled
//		Element tcpIpSmbElement = getChildNode( "tcpipSMB", host.getChildNodes() );
//		if ( tcpIpSmbElement != null ) {
//			
//			// Check if native SMB is enabled for the current platform
//			if ( tcpIpSmbElement.hasAttribute( "platforms" ) ) {
//				
//				if ( isCurrentPlatformIncluded( tcpIpSmbElement.getAttribute( "platforms" ) ) ) {
//					
//					// Enable the TCP/IP SMB support
//					cifsConfig.setTcpipSMB( true );
//					
//					// Check if the port has been specified
//					String smbPortAttribute = tcpIpSmbElement.getAttribute( "port" );
//					if ( smbPortAttribute != null && smbPortAttribute.length() > 0 ) {
//						
//						Integer smbPort = convertStringToPortNumber( smbPortAttribute );
//						if ( smbPort == null ) {
//							
//							throw new InvalidConfigurationException( "Invalid TCP/IP SMB port" );
//						}
//						cifsConfig.setTcpipSMBPort( smbPort );
//					}
//					
//					// Check if IPv6 support should be enabled
//					String ipv6 = tcpIpSmbElement.getAttribute( "ipv6" );
//					if ( ipv6 != null && ipv6.equalsIgnoreCase( "enabled" ) ) {
//						
//						try {
//							
//							// Use the IPv6 bind all address
//							cifsConfig.setSMBBindAddress( InetAddress.getByName( "::" ) );
//						}
//						catch ( UnknownHostException ex ) {
//							
//							throw new InvalidConfigurationException( "Failed to enable IPv6 bind address, " + ex.getMessage() );
//						}
//					}
//				}
//				else {
//					
//					// Disable the TCP/IP SMB support
//					cifsConfig.setTcpipSMB( false );
//				}
//			}
//		}
//		else {
//			
//			// Disable TCP/IP SMB support
//			cifsConfig.setTcpipSMB( false );
//		}
//		
//		// Check that the broadcast mask has been set if TCP/IP NetBIOS and/or the host announcer is enabled
//		if ( cifsConfig.hasNetBIOSSMB() || cifsConfig.hasEnableAnnouncer() ) {
//			
//			// Parse the broadcast mask
//			Element broadcastElement = getChildNode( "broadcast", host.getChildNodes() );
//			if ( broadcastElement != null ) {
//				
//				// Check if the broadcast mask is a valid numeric IP address
//				if ( !IPAddress.isNumericAddress( getText( broadcastElement ) ) ) {
//					
//					throw new InvalidConfigurationException( "Invalid broadcast mask, must be n.n.n.n format" );
//				}
//				
//				cifsConfig.setBroadcastMask( getText( broadcastElement ) );
//			}
//			else {
//				
//				// Broadcast mask not configured
//				throw new InvalidConfigurationException( "Network broadcast mask not specified" );
//			}
//		}
//		
//		// Check if Win32 NetBIOS is enabled
//		Element win32NetBiosElement = getChildNode( "Win32NetBIOS", host.getChildNodes() );
//		if ( win32NetBiosElement != null ) {
//			
//			// Check if the Win32 NetBIOS server name has been specified
//			String win32NetBiosServerName = win32NetBiosElement.getAttribute( "name" );
//			if ( win32NetBiosServerName != null && win32NetBiosServerName.length() > 0 ) {
//				
//				// Validate the name
//				if ( win32NetBiosServerName.length() > 16 ) {
//					
//					throw new InvalidConfigurationException( "Invalid Win32 NetBIOS name, " + win32NetBiosServerName );
//				}
//				
//				// Set the Win32 NetBIOS file server name
//				cifsConfig.setWin32NetBIOSName( win32NetBiosServerName );
//			}
//			
//			// Check if the Win32 NetBIOS client accept name has been specified
//			String win32NetBiosClientName = win32NetBiosElement.getAttribute( "accept" );
//			if ( win32NetBiosClientName != null && win32NetBiosClientName.length() > 0 ) {
//				
//				// Validate the client accept name
//				if ( win32NetBiosClientName.length() > 15 ) {
//					
//					throw new InvalidConfigurationException( "Invalid Win32 NetBIOS accept name, " + win32NetBiosClientName );
//				}
//				
//				// Set the client accept string
//				cifsConfig.setWin32NetBIOSClientAccept( win32NetBiosClientName );
//			}
//			
//			// Check if the Win32 NetBIOS LANA has been specified
//			String win32NetBiosLana = win32NetBiosElement.getAttribute( "lana" );
//			if ( win32NetBiosLana != null && win32NetBiosLana.length() > 0 ) {
//				
//				// Check if the LANA has been specified as an IP address or adapter name
//				int lana = -1;
//				if ( IPAddress.isNumericAddress( win32NetBiosLana ) ) {
//					
//					// Convert the IP address to a LANA id
//					lana = Win32NetBIOS.getLANAForIPAddress( win32NetBiosLana );
//					if ( lana == -1 ) {
//						
//						throw new InvalidConfigurationException( "Failed to convert IP address " + win32NetBiosLana + " to a LANA" );
//					}
//				}
//				else if ( win32NetBiosLana.length() > 1 && Character.isLetter( win32NetBiosLana.charAt( 0 ) ) ) {
//					
//					// Convert the network adapter to a LANA id
//					lana = Win32NetBIOS.getLANAForAdapterName( win32NetBiosLana );
//					if ( lana == -1 ) {
//						
//						throw new InvalidConfigurationException( "Failed to convert network adapter " + win32NetBiosLana + " to a LANA" );
//					}
//				}
//				else {
//					
//					// Validate the LANA number
//					try {
//						
//						lana = Integer.parseInt( win32NetBiosLana );
//					}
//					catch ( NumberFormatException ex ) {
//						
//						throw new InvalidConfigurationException( "Invalid Win32 NetBIOS LANA specified" );
//					}
//					
//					// LANA should be in the range 0-255
//					if ( lana < 0 || lana > 255 ) {
//						
//						throw new InvalidConfigurationException( "Invalid Win32 NetBIOS LANA number, " + lana );
//					}
//				}
//				
//				// Set the LANA number
//				cifsConfig.setWin32LANA( lana );
//			}
//			
//			// Check if the native NetBIOS interface has been specified, either 'winsock' or 'netbios'
//			String api = win32NetBiosElement.getAttribute( "api" );
//			if ( api != null && api.length() > 0 ) {
//				
//				boolean useWinsock = api.equalsIgnoreCase( "winsock" );
//				if ( !useWinsock && !api.equalsIgnoreCase( "netbios" ) ) {
//					
//					throw new InvalidConfigurationException( "Invalid NetBIOS API type, spefify 'winsock' or 'netbios'" );
//				}
//				
//				// Set the NetBIOS API to use
//				cifsConfig.setWin32WinsockNetBIOS( useWinsock );
//			}
//			
//			// Force the older NetBIOS API code to be used on 64Bit Windows as Winsock NetBIOS is not available
//			if ( cifsConfig.useWinsockNetBIOS() && X64.isWindows64() ) {
//				
//				// TODO: switch to log4j
//				// Use the older NetBIOS API code
//				Debug.println( "Using older Netbios() API code, Winsock NetBIOS not available on x64" );
//				cifsConfig.setWin32WinsockNetBIOS( false );
//			}
//			
//			// Check if the current operating system is supported by the Win32 NetBIOS handler
//			String osName = System.getProperty( "os.name" );
//			boolean useWin32NetBios = (osName.startsWith( "Windows" ) && (!osName.endsWith( "95" ) && !osName.endsWith( "98" ) && !osName.endsWith( "ME" )));
//			cifsConfig.setWin32NetBIOS( useWin32NetBios );
//		}
//		else {
//			
//			// Disable Win32 NetBIOS
//			cifsConfig.setWin32NetBIOS( false );
//		}
//		
//		// Check if the host announcer should be enabled
//		Element win32Announce = getChildNode( "Win32Announce", host.getChildNodes() );
//		if ( win32Announce != null ) {
//			
//			// Check for an announcement interval
//			String interval = win32Announce.getAttribute( "interval" );
//			if ( interval != null && interval.length() > 0 ) {
//				
//				try {
//					
//					cifsConfig.setWin32HostAnnounceInterval( Integer.parseInt( interval ) );
//				}
//				catch ( NumberFormatException ex ) {
//					
//					throw new InvalidConfigurationException( "Invalid host announcement interval" );
//				}
//			}
//			
//			// Check if the domain name has been set, this is required if the host announcer is enabled
//			if ( cifsConfig.getDomainName() == null ) {
//				
//				throw new InvalidConfigurationException( "Domain name must be specified if host announcement is enabled" );
//			}
//			
//			cifsConfig.setWin32HostAnnouncer( true );
//		}
//		
//		// Check if NetBIOS and/or TCP/IP SMB have been enabled
//		if ( !cifsConfig.hasNetBIOSSMB() && !cifsConfig.hasTcpipSMB() && !cifsConfig.hasWin32NetBIOS() ) {
//			
//			throw new InvalidConfigurationException( "NetBIOS SMB, TCP/IP SMB or Win32 NetBIOS must be enabled" );
//		}
//		
//		// Check if server alias name(s) have been specified
//		Element aliasElement = getChildNode( "alias", host.getChildNodes() );
//		if ( aliasElement != null ) {
//			
//			// Get the alias name list
//			String aliases = aliasElement.getAttribute( "names" );
//			if ( aliases == null || aliases.length() == 0 ) {
//				
//				throw new InvalidConfigurationException( "Alias name(s) not specified" );
//			}
//			
//			// Parse the alias name list
//			Pattern pattern = Pattern.compile( ALIASES_REGEX );
//			Matcher matcher = pattern.matcher( aliases );
//			StringList names = new StringList();
//			
//			while ( matcher.find() ) {
//				
//				// Get the current alias name
//				String alias = matcher.group().toUpperCase();
//				
//				// Check if the name already exists in the alias list, or matches the main server name
//				if ( alias.equalsIgnoreCase( getServerName() ) ) {
//					
//					throw new InvalidConfigurationException( "Alias is the same as the main server name" );
//				}
//				else if ( names.containsString( alias ) ) {
//					
//					throw new InvalidConfigurationException( "Same alias specified twice, " + alias );
//				}
//				else {
//					
//					names.addString( alias );
//				}
//			}
//			
//			// Set the server alias names
//			cifsConfig.addAliasNames( names );
//		}
//		
//		// Check if Macintosh extension SMBs should be enabled
//		Element macExtensionsElement = getChildNode( "macExtensions", host.getChildNodes() );
//		if ( macExtensionsElement != null ) {
//			
//			cifsConfig.setMacintoshExtensions( true );
//		}
//		
//		// Check if WINS servers are configured
//		Element winsElement = getChildNode( "WINS", host.getChildNodes() );
//		if ( winsElement != null ) {
//			
//			// Get the primary WINS server
//			Element primaryServer = getChildNode( "primary", winsElement.getChildNodes() );
//			if ( primaryServer == null ) {
//				
//				throw new InvalidConfigurationException( "No primary WINS server configured" );
//			}
//			
//			// Validate the WINS server address
//			try {
//				
//				cifsConfig.setPrimaryWINSServer( InetAddress.getByName( getText( primaryServer ) ) );
//			}
//			catch ( UnknownHostException ex ) {
//				
//				throw new InvalidConfigurationException( "Invalid primary WINS server address, " + primaryServer.getNodeValue() );
//			}
//			
//			// Check if a secondary WINS server has been specified
//			Element secondaryServer = getChildNode( "secondary", winsElement.getChildNodes() );
//			if ( secondaryServer != null ) {
//				
//				// Validate the secondary WINS server address
//				try {
//					
//					cifsConfig.setSecondaryWINSServer( InetAddress.getByName( getText( secondaryServer ) ) );
//				}
//				catch ( UnknownHostException ex ) {
//					
//					throw new InvalidConfigurationException( "Invalid secondary WINS server address, " + secondaryServer.getNodeValue() );
//				}
//			}
//		}
//		
//		// Check if a session timeout is configured
//		Element sessionTimeoutElement = getChildNode( "sessionTimeout", host.getChildNodes() );
//		if ( sessionTimeoutElement != null ) {
//			
//			// Validate the session timeout value
//			String sessionTimeOut = getText( sessionTimeoutElement );
//			if ( sessionTimeOut != null && sessionTimeOut.length() > 0 ) {
//				
//				try {
//					
//					// Convert the timeout value to milliseconds
//					int timeout = Integer.parseInt( sessionTimeOut );
//					if ( timeout < 0 || timeout > MaxSessionTimeout ) {
//						
//						throw new InvalidConfigurationException( "Session timeout out of range (0 - " + MaxSessionTimeout + ")" );
//					}
//					
//					// Convert the session timeout to milliseconds
//					cifsConfig.setSocketTimeout( timeout * 1000 );
//				}
//				catch ( NumberFormatException ex ) {
//					
//					throw new InvalidConfigurationException( "Invalid session timeout value, " + sessionTimeOut );
//				}
//			}
//			else {
//				
//				throw new InvalidConfigurationException( "Session timeout value not specified" );
//			}
//		}
//		
//		// Check if the NIO based socket code should be disabled
//		Element disableNioElement = getChildNode( "disableNIO", host.getChildNodes() );
//		if ( disableNioElement != null ) {
//			
//			// Disable NIO based code
//			cifsConfig.setDisableNIOCode( true );
//		}
//	}
//	
//	/**
//	 * Validate a port number
//	 * 
//	 * @param portNumber String
//	 * @return boolean
//	 */
//	private final Integer convertStringToPortNumber( String portNumber ) {
//
//		Integer port = null;
//		try {
//			
//			Integer temp = Integer.parseInt( portNumber );
//			if ( temp >= 0 || temp <= 65535 ) {
//				
//				port = temp;
//			}
//		}
//		catch ( NumberFormatException ex ) {
//
//			// Do not set port
//		}
//		return port;
//	}
//	
//	/**
//	 * Process the debug XML element
//	 * 
//	 * @param debug Element
//	 * @exception InvalidConfigurationException
//	 */
//	protected final void procDebugElement( Element debug ) throws InvalidConfigurationException {
//
//		// Check if the debug section has been specified
//		if ( debug == null ) {
//			
//			return;
//		}
//		
//		// Create the debug configuration section
//		DebugConfigSection debugConfig = new DebugConfigSection( this );
//		
//		// Get the debug output class and parameters
//		Element outputElement = getChildNode( "output", debug.getChildNodes() );
//		if ( outputElement == null ) {
//			
//			throw new InvalidConfigurationException( "Output class must be specified to enable debug output" );
//		}
//		
//		// Get the debug output class
//		Element debugClass = getChildNode( "class", outputElement.getChildNodes() );
//		if ( debugClass == null ) {
//			
//			throw new InvalidConfigurationException( "Class must be specified for debug output" );
//		}
//		
//		// Get the parameters for the debug class
//		ConfigElement params = buildConfigElement( outputElement, null );
//		debugConfig.setDebug( getText( debugClass ), params );
//	}
//	
//	/**
//	 * Add a disk share for Google Docs
//	 * 
//	 * @param docsService DocsService
//	 * @param name String
//	 * @param comment String
//	 * @exception InvalidConfigurationException
//	 */
//	protected final void addDiskShare( String name, String comment ) throws InvalidConfigurationException {
//		
//		// Get the share name and comment
//		if ( name == null || name.length() == 0 ) {
//			
//			throw new IllegalArgumentException( "Disk share name must be specified" );
//		}
//		
//		// Check if a share with this name already exists
//		FilesystemsConfigSection filesystemsConfig = (FilesystemsConfigSection) getConfigSection( FilesystemsConfigSection.SectionName );
//		if ( filesystemsConfig.getShares().findShare( name ) != null ) {
//			
//			throw new IllegalArgumentException( "Share " + name + " already exists" );
//		}
//		
//		SecurityConfigSection securityConfig = (SecurityConfigSection) getConfigSection( SecurityConfigSection.SectionName );
//		AccessControlList acls = securityConfig.getGlobalAccessControls();
//		
//		// Create volume information using the share name
//		VolumeInfo volInfo = new VolumeInfo( name, (int) System.currentTimeMillis(), new Date( System.currentTimeMillis() ) );
//			
//		// Default to a 80Gb sized disk with 90% free space
//		// TODO: set parameters to stuff from google docs
//		SrvDiskInfo diskInfo = null; //new SrvDiskInfo( 2560000, 64, 512, 2304000 );
//		
//		// Create a device context and add the new disk share
//		try {
//			
//			// Create the driver
//			DiskInterface diskDrive = (DiskInterface) new CumulusFractoDiskDrive( );
//			
//			// Create a context for this share instance, save the configuration parameters as part of the context
//			GenericConfigElement params = new GenericConfigElement( "driver" );
//			DiskDeviceContext deviceContext = (DiskDeviceContext) diskDrive.createContext( name, params );
//			deviceContext.setConfigurationParameters( params );
//			deviceContext.enableChangeHandler( false );
//			
//			// Set the volume information, may be null
//			deviceContext.setVolumeInformation( volInfo );
//			
//			// Set the disk sizing information, may be null
//			deviceContext.setDiskInformation( diskInfo );
//			deviceContext.setShareName( name );
//			
//			// Create the disk shared device and add to the server's list of shares
//			DiskSharedDevice diskDev = new DiskSharedDevice( name, diskDrive, deviceContext );
//			diskDev.setComment( comment );
//			diskDev.setAccessControlList( acls );
//			deviceContext.startFilesystem( diskDev );
//			filesystemsConfig.addShare( diskDev );
//		}
//		catch ( DeviceContextException ex ) {
//			
//			throw new InvalidConfigurationException( "Driver context error: " + ex.getMessage() );
//		}
//		catch ( Exception ex ) {
//			
//			throw new InvalidConfigurationException( "Disk share setup error, " + ex.getMessage() );
//		}
//	}
//	
//	/**
//	 * Add a disk share for Google Docs
//	 * 
//	 * @param docsService DocsService
//	 * @param name String
//	 * @param comment String
//	 * @exception InvalidConfigurationException
//	 */
//	protected final void removeDiskShare( String name ) throws InvalidConfigurationException {
//		
//		// Get the share name and comment
//		if ( name == null || name.length() == 0 ) {
//			
//			throw new IllegalArgumentException( "Disk share name must be specified" );
//		}
//		
//		// Check if a share with this name exists
//		FilesystemsConfigSection filesystemsConfig = (FilesystemsConfigSection) getConfigSection( FilesystemsConfigSection.SectionName );
//		if ( filesystemsConfig.getShares().findShare( name ) != null ) {
//			
//			filesystemsConfig.getShares().deleteShare( name );
//		}
//	}
//	
//	/**
//	 * Find the specified child node in the node list
//	 * 
//	 * @param name String
//	 * @param list NodeList
//	 * @return Element
//	 */
//	protected final Element getChildNode( String name, NodeList list ) {
//		
//		Node child = null;
//		boolean found = false;
//		
//		// Check if the list is valid
//		if ( list != null ) {
//			
//			// Search for the required element
//			int i = 0;
//			while ( i < list.getLength() && !found ) {
//				
//				child = list.item( i );
//				found = child.getNodeName().equals( name ) && child.getNodeType() == ELEMENT_TYPE;
//				i++;
//			}
//		}
//		
//		return ( found ) ? (Element) child : null;
//	}
//	
//	/**
//	 * Get the value text for the specified element
//	 * 
//	 * @param elem Element
//	 * @return String
//	 */
//	protected final String getText( Element elem ) {
//
//		// Check if the element has children
//		NodeList children = elem.getChildNodes();
//		return ( children != null && children.getLength() > 0 && children.item( 0 ).getNodeType() != ELEMENT_TYPE ) ? children.item( 0 ).getNodeValue() : "";
//	}
//	
//	/**
//	 * Build a configuration element list from an elements child nodes
//	 * 
//	 * @param root Element
//	 * @param cfgElem GenericConfigElement
//	 * @return GenericConfigElement
//	 */
//	protected final GenericConfigElement buildConfigElement( Element root, GenericConfigElement cfgElem ) {
//
//		// Create the top level element, if not specified
//		GenericConfigElement rootElem = cfgElem;
//		
//		if ( rootElem == null ) {
//			
//			// Create the root element
//			rootElem = new GenericConfigElement( root.getNodeName() );
//			
//			// Add any attributes
//			NamedNodeMap attribs = root.getAttributes();
//			if ( attribs != null ) {
//				
//				for ( int i = 0; i < attribs.getLength(); i++ ) {
//					
//					Node attribNode = attribs.item( i );
//					rootElem.addAttribute( attribNode.getNodeName(), attribNode.getNodeValue() );
//				}
//			}
//		}
//		
//		// Get the child node list
//		NodeList nodes = root.getChildNodes();
//		if ( nodes != null ) {
//			
//			// Process the child node list
//			GenericConfigElement childElem = null;
//			
//			for ( int i = 0; i < nodes.getLength(); i++ ) {
//				
//				// Get the current node
//				Node node = nodes.item( i );
//				if ( node.getNodeType() == ELEMENT_TYPE ) {
//					
//					Element elem = (Element) node;
//					
//					NodeList children = elem.getChildNodes();
//					if ( children != null && children.getLength() > 1 ) {
//						
//						// Add the child nodes as child configuration elements
//						childElem = buildConfigElement( elem, null );
//					}
//					else {
//						
//						// Create a normal name/value
//						if ( children.getLength() > 0 ) {
//							
//							childElem = new GenericConfigElement( elem.getNodeName() );
//							childElem.setValue( children.item( 0 ).getNodeValue() );
//						}
//						else {
//							
//							childElem = new GenericConfigElement( elem.getNodeName() );
//						}
//						
//						// Add any attributes
//						NamedNodeMap attribs = elem.getAttributes();
//						if ( attribs != null ) {
//							
//							for ( int j = 0; j < attribs.getLength(); j++ ) {
//								
//								Node attribNode = attribs.item( j );
//								childElem.addAttribute( attribNode.getNodeName(), attribNode.getNodeValue() );
//							}
//						}
//					}
//					
//					// Add the child configuration element
//					rootElem.addChild( childElem );
//				}
//			}
//		}
//		
//		// Return the configuration element
//		return rootElem;
//	}
//	
//	/**
//	 * Checks to see if the system platform is in the given delimited string platforms
//	 * 
//	 * @param platforms String
//	 * @return List<Integer>
//	 * @exception InvalidConfigurationException
//	 */
//	protected final boolean isCurrentPlatformIncluded( String platforms ) throws InvalidConfigurationException {
//		
//		boolean isValid = false;
//		
//		if ( platforms != null ) {
//			
//			Platform.Type systemPlatform = getPlatformType();
//			Pattern pattern = Pattern.compile( PLATFORMS_REGEX );
//			Matcher matcher = pattern.matcher( platforms.toUpperCase( Locale.ENGLISH ) );
//			
//			while ( matcher.find() && !isValid ) {
//				
//				String group = matcher.group();
//				try {
//					
//					Platform.Type tempPlatform = Platform.Type.valueOf( group );
//					isValid = tempPlatform.equals( systemPlatform );
//				}
//				catch ( Exception e ) {
//					
//					throw new InvalidConfigurationException( "Invalid platform type '" + group + "'" );
//				}
//			}
//		}
//		
//		return isValid;
//	}
//	
//	/**
//	 * Parse an adapter name string and return the matching address
//	 * 
//	 * @param adapter String
//	 * @return InetAddress
//	 * @exception InvalidConfigurationException
//	 */
//	protected final InetAddress parseAdapterName( String adapter ) throws InvalidConfigurationException {
//
//		NetworkInterface ni = null;
//		
//		try {
//			
//			ni = NetworkInterface.getByName( adapter );
//		}
//		catch ( SocketException ex ) {
//			
//			throw new InvalidConfigurationException( "Invalid adapter name, " + adapter );
//		}
//		
//		if ( ni == null ) {
//			
//			throw new InvalidConfigurationException( "Invalid network adapter name, " + adapter );
//		}
//		
//		// Get the IP address for the adapter
//		InetAddress adapAddr = null;
//		Enumeration<InetAddress> addrEnum = ni.getInetAddresses();
//		
//		while ( addrEnum.hasMoreElements() && adapAddr == null ) {
//			
//			// Get the current address
//			InetAddress addr = addrEnum.nextElement();
//			if ( IPAddress.isNumericAddress( addr.getHostAddress() ) ) {
//				
//				adapAddr = addr;
//			}
//		}
//		
//		// Check if we found the IP address to bind to
//		if ( adapAddr == null ) {
//			
//			throw new InvalidConfigurationException( "Adapter " + adapter + " does not have a valid IP address" );
//		}
//		
//		// Return the adapter address
//		return adapAddr;
//	}
//
//	@Override
//	public int configurationChanged( int arg0, ServerConfiguration arg1, Object arg2 ) throws InvalidConfigurationException {
//
//		// TODO Auto-generated method stub
//		return 0;
//	}
}
